﻿using Alphacat.Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace Alphacat.Controller
{
    class TaskWork
    {
        //支持的文件类型
        string[] Supported_File_Type = {
                "doc", "docx",
                "ppt", "pptx",
                "xls", "xlsx",
                "txt", "pdf"
        };

        public WXService wxs;

        public Queue<FileTask> RecWxMsgQueue = null;                                 //接受消息队列
        public Queue<FileTask> SenWxMsgQueue = null;                                 //发送消息队列

        public List<FileTask> ReceWxMsgList = null;
        public List<FileTask> SendWxMsgList = null;

        public BackgroundWorker[] taskWorker = null;                                 //后台线程
        public BackgroundWorker[] doWorker = null;                                   //做任务的后台线程
        public bool[] status = new bool[3] { true, true, true };                          //线程状态信号量
        public int[] time = new int[3] { 2000, 1000, 500 };                               //线程循环时间

        public int taskRetryTimeMax = 3;                                            //任务重试次数

        public TaskWork(WXService wxs)
        {
            this.wxs = wxs;
            this.taskWorker = new BackgroundWorker[3];                             //三个循环线程 1.接收微信消息 2.发送微信消息 3.处理任务
            this.RecWxMsgQueue = new Queue<FileTask>();                            //接收微信消息队列
            this.SenWxMsgQueue = new Queue<FileTask>();                            //发送微信消息队列

            ReceWxMsgList = new List<FileTask>();
            SendWxMsgList = new List<FileTask>();

            this.status = new bool[3] { true, true, true };                        //线程循环状态
            this.time = new int[3] { 2000, 1000, 500 };                            //处理任务时间
            this.doWorker = new BackgroundWorker[3];                               //三线程处理任务

            for (int i = 0; i < 3; i++)
            {
                this.taskWorker[i] = new BackgroundWorker();
                this.doWorker[i] = new BackgroundWorker();
            }

            taskWorker[0].DoWork += new DoWorkEventHandler(TaskDoWork_RecWxMsg);   //接受消息
            taskWorker[1].DoWork += new DoWorkEventHandler(TaskDoWork_SenWxMsg);   //发送消息
            taskWorker[2].DoWork += new DoWorkEventHandler(WxMsgTaskDoWork);       //执行任务
            for (int i = 0; i < 3; i++)
            {
                this.doWorker[i].DoWork += new DoWorkEventHandler(uploadWork);     //绑定三个处理线程事件
            }

            
        }
        

        //接收微信消息
        private void TaskDoWork_RecWxMsg(object sender, DoWorkEventArgs e)
        {

            string sync_flag = "";
            JObject sync_result;

            while (status[0])
            {

                sync_flag = wxs.WxSyncCheck();  //同步检查
                //Console.WriteLine(sync_flag);
                if (sync_flag == null)
                {
                    continue;
                }
                //这里应该判断 sync_flag中selector的值
                else //有消息
                {
                    sync_result = wxs.WxSync();  //进行同步
                    if (sync_result != null)
                    {
                        if (sync_result["AddMsgCount"] != null && sync_result["AddMsgCount"].ToString() != "0")
                        {
                            foreach (JObject m in sync_result["AddMsgList"])
                            {

                                string from = m["FromUserName"].ToString();
                                string to = m["ToUserName"].ToString();
                                string content = m["Content"].ToString();
                                string type = m["MsgType"].ToString();
                                if (type == "51")  //屏蔽一些系统数据
                                {
                                    continue;
                                }
                                switch (type)
                                {
                                    case "1":
                                        //ACLog("收到文本消息:\r\n发送方: " + from + "\r\n内容: " + content);
                                        //ACLog(m.ToString());
                                        //AutoReplyTextMsg(content, to, from);
                                        Console.WriteLine("收到文本消息:\r\n发送方: " + from + "\r\n内容: " + content);
                                        AutoReplyTextMsg(content, to, from);
                                        break;
                                    case "3":
                                        Console.WriteLine("收到图片消息:\r\n发送方: " + from);
                                        MakeImageTask(m);
                                        //ACLog("收到图片消息:\r\n发送方: " + from);
                                        break;
                                    case "49":
                                        //ACLog("收到文件消息:\r\n发送方: " + from + "\r\n文件名: " + m["FileName"].ToString());
                                        //ACLog(m.ToString());
                                        //handleFileMsg(m);
                                        Console.WriteLine("收到文件消息:\r\n发送方: " + from + "\r\n文件名: " + m["FileName"].ToString());
                                        RecvWxMsgDoWork(m);//插入微信消息
                                                                              //执行获取微信消息的网络请求
                                        break;
                                    default:
                                        //ACLog("收到无关消息:\r\n发送方: " + from + "\r\n内容: " + content);
                                        Console.WriteLine("收到无关消息:\r\n发送方: " + from + "\r\n内容: " + content);
                                        break;
                                }


                            }
                        }
                    }

                    
                    System.Threading.Thread.Sleep(time[0]);
                }
            }
        }

        //发送微信消息
        private void TaskDoWork_SenWxMsg(object sender, DoWorkEventArgs e)
        {
            while (status[1])
            {
                //if (SenWxMsgQueue.Count == 0)
                //{
                //    System.Threading.Thread.Sleep(time[0]);
                //    continue;
                //}
                //FileTask fileObj = SenWxMsgQueue.Dequeue();

                if (SendWxMsgList.Count == 0)
                {
                    continue;
                }

                FileTask fileObj = SendWxMsgList.First();
                SendWxMsgList.RemoveAt(0);

                byte[] picData = fileObj.codeImgData;
                string from = fileObj.FromUserID;
                string me = fileObj.MyUserID;
                string realFileName = fileObj.RealFileName;

                try
                {
                    if (fileObj.msgType == FileTaskType.Text)
                    {
                        wxs.SendMsg(fileObj.msgText, me, from, 1);
                    }
                    else
                    {
                        //执行获取微信消息的网络请求
                        string res = BaseService.UploadFileWithBytes(picData, me, from);

                        //ACLog("上传code结果:\r\n" + res);
                        //Console.WriteLine("上传code结果:\r\n" + res);

                        JObject sendRes = JsonConvert.DeserializeObject(res) as JObject;
                        string mediaid = sendRes["MediaId"].ToString();
                        wxs.SendImgMsg(mediaid, me, from);
                        System.Threading.Thread.Sleep(time[1]);
                        wxs.SendMsg("文件 " + realFileName + " 处理完成，请到打印终端扫码打印，有效期48小时。", me, from, 1);
                    }
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.StackTrace);
                    if (fileObj.sendRetryTime < taskRetryTimeMax)
                    {
                        fileObj.sendRetryTime++;
                        SendWxMsgList.Insert(0, fileObj);
                    }
                    else
                    {
                        fileObj.sendRetryTime = 0;
                        SendWxMsgList.Add(fileObj);
                    }
                    

                    //SenWxMsgQueue.Enqueue(fileObj);
                }
                
                System.Threading.Thread.Sleep(time[1]);
            }
        }
        //执行任务
        public void WxMsgTaskDoWork(object sender, DoWorkEventArgs e)
        {
            while (status[2])
            {
                StartUploadDoWork();
                //执行文件操作
                System.Threading.Thread.Sleep(time[0]);
            }
        }

        // 文件下载&上传任务
        private void uploadWork(object sender, DoWorkEventArgs e)
        {
            
            FileTask fileObj = (FileTask)e.Argument;
            string fileUrl = fileObj.Url;
            string from = fileObj.FromUserID;
            string me = fileObj.MyUserID;

            string filename = fileObj.FileName;
            string realFileName = fileObj.RealFileName;

            try
            {
                if (fileObj.fileData == null)
                {
                    byte[] filedata = BaseService.SendGetRequest(fileUrl);

                    if (filedata == null)
                    {
                        throw new NullReferenceException("filedata null");
                    }
                    fileObj.fileData = filedata;
                }

                if (fileObj.code == null)
                {
                    string uploadRes = BaseService.UploadServerWithBytes(fileObj.fileData, realFileName);
                    JObject uploadObj = JsonConvert.DeserializeObject(uploadRes) as JObject;
                    string status = uploadObj["status"].ToString();

                    if (status != "200")
                    {
                        throw new Exception("upload server error");
                    }

                    string ornum = uploadObj["data"]["ornum"].ToString();

                    if (ornum == null)
                    {
                        throw new NullReferenceException("ornum null");
                    }

                    fileObj.code = ornum;
                }

                if (fileObj.codeImgData == null)
                {
                    byte[] picData = QRCode.GetQRCodeBytes(fileObj.code);

                    if (picData == null)
                    {
                        throw new NullReferenceException("code img null");
                    }

                    fileObj.codeImgData = picData;
                }

                // 完成，进入等待回复队列
                //SenWxMsgQueue.Enqueue(fileObj);

                SendWxMsgList.Add(fileObj);
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex);

                //重新入队
                //RecWxMsgQueue.Enqueue(fileObj);

                if (fileObj.receRetryTime < taskRetryTimeMax)
                {
                    fileObj.receRetryTime++;
                    ReceWxMsgList.Insert(0, fileObj);
                }
                else
                {
                    fileObj.receRetryTime = 0;
                    ReceWxMsgList.Add(fileObj);
                }
            }
            
        }
        //形成一个文件任务
        public void RecvWxMsgDoWork(JObject msg)
        {
            
            string sender = msg["FromUserName"].ToString();
            string mediaid = msg["MediaId"].ToString();
            string filename = msg["FileName"].ToString();
            string msgid = msg["MsgId"].ToString();
            string me = msg["ToUserName"].ToString();

            string[] fileNameCompo = filename.Split('.'); // 分割文件名，获取文件类型
            string fileType = "";
            bool support = false;
            if (fileNameCompo.Length >= 2)
            {
                fileType = fileNameCompo.Last();
                foreach (string supportType in Supported_File_Type)
                {
                    if (fileType == supportType)
                    {
                        support = true;
                        break;
                    }
                }
            }
            if (!support) // 文件类型不支持
            {
                return;
            }
            string fromuser = BaseService.GetCookie("wxuin").Value;
            string passTicket = BaseService.PassTicket;
            string dataTicket = BaseService.GetCookie("webwx_data_ticket").Value;

            string fileUrl = "https://file.wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia?";
            fileUrl += "sender=" + sender;
            fileUrl += "&mediaid=" + mediaid;
            fileUrl += "&filename=" + HttpUtility.UrlEncode(filename);
            fileUrl += "&fromuser=" + fromuser;
            fileUrl += "&passTicket=" + passTicket;
            fileUrl += "&dataTicket=" + dataTicket;
            //fileUrl = HttpUtility.UrlEncode(fileUrl, Encoding.GetEncoding("gbk"));

            string thisFileName = msgid + "." + fileType;
            //docPath += "/" + thisFileName;
            //ACLog("文件: " + fileUrl);

            FileTask ft = new FileTask(fileUrl, thisFileName, sender, me, filename);

            //RecWxMsgQueue.Enqueue(ft);
            ReceWxMsgList.Add(ft);
        }

        public void MakeImageTask(JObject msg)
        {
            string sender = msg["FromUserName"].ToString();
            string mediaid = msg["MediaId"].ToString();
            string msgid = msg["MsgId"].ToString();
            string me = msg["ToUserName"].ToString();

            string skey = BaseService.Skey;

            string imgUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg?";
            imgUrl += "MsgID=" + msgid;
            imgUrl += "&skey=" + skey;

            string thisFileName = msgid + ".jpg";
            string realFileName = "image" + DateTime.Now.ToString("yyyyMMddHHmmssffffff") + ".jpg";

            FileTask ft = new FileTask(imgUrl, thisFileName, sender, me, realFileName);

            //RecWxMsgQueue.Enqueue(ft);
            ReceWxMsgList.Add(ft);
        }

        // 回复微信文本
        public void AutoReplyTextMsg(string msg, string me, string to)
        {
            string replyMsg = "";
            switch (msg)
            {
                case "测试":
                    replyMsg = "这是测试这是测试这是测试这是测试";
                    break;
                default:
                    break;
            }
            if (replyMsg != "")
            {
                FileTask fileObj = new FileTask(replyMsg, to, me);
                SendWxMsgList.Add(fileObj);
            }

        }

        //开启Task任务
        public void StartDoWork()
        {
            for (int i = 0; i < taskWorker.Length; i++)
            {
                taskWorker[i].RunWorkerAsync();
            }
        }
        //开始上传文件
        public void StartUploadDoWork()
        {
            for (int i = 0; i < 3; i++)
            {
                //if (!this.doWorker[i].IsBusy && RecWxMsgQueue.Count != 0)
                //{
                //    this.doWorker[i].RunWorkerAsync(RecWxMsgQueue.Dequeue());//不繁忙则启动线程
                //}

                if (!doWorker[i].IsBusy && ReceWxMsgList.Count != 0)
                {

                    FileTask fileObj = ReceWxMsgList.First();
                    ReceWxMsgList.RemoveAt(0);
                    doWorker[i].RunWorkerAsync(fileObj);
                }
            }

        }

        //关闭Task任务
        public void StopWork()
        {
            for (int i = 0; i < status.Length; i++)
            {
                status[i] = false;
            }
        }
    }
}
